package com.genymobile.scrcpy.wrappers;

import com.genymobile.scrcpy.dto.ShellResult;
import com.genymobile.scrcpy.util.Ln;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;

public class ShellManager {

    private static class StreamReader implements Runnable {
        private final InputStream inputStream;
        private final StringBuilder buffer;

        StreamReader(InputStream inputStream, StringBuilder buffer) {
            this.inputStream = inputStream;
            this.buffer = buffer;
        }

        @Override
        public void run() {
            readStream(inputStream, buffer);
        }
    }

    private static final String TAG = "ShellManager";
    private static final long DEFAULT_TIMEOUT = 30_000;

    public static ShellResult executeShellCommandSync(String command) throws IOException, InterruptedException {
        return executeShellCommandSync(command, DEFAULT_TIMEOUT);
    }

    public static ShellResult executeShellCommandSync(String command, long timeoutMillis) throws IOException, InterruptedException {
        Process process = null;
        Thread outputThread = null;
        Thread errorThread = null;
        try {
            ProcessBuilder processBuilder = new ProcessBuilder("sh", "-c", command);
            process = processBuilder.start();

            // 使用StringBuilder收集输出
            StringBuilder outputBuffer = new StringBuilder();
            StringBuilder errorBuffer = new StringBuilder();

            // 启动线程读取输出流
            outputThread = new Thread(new StreamReader(process.getInputStream(), outputBuffer), "shell-output-reader");
            errorThread = new Thread(new StreamReader(process.getErrorStream(), errorBuffer), "shell-error-reader");

            outputThread.start();
            errorThread.start();

            // 等待进程结束或超时
            boolean finished = false;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                finished = process.waitFor(timeoutMillis, TimeUnit.MILLISECONDS);
            }
            if (!finished) {
                process.destroy();
                if (outputThread.isAlive()) outputThread.interrupt();
                if (errorThread.isAlive()) errorThread.interrupt();
                throw new IOException("Command execution timed out");
            }

            // 等待读取线程完成
            outputThread.join(500);
            errorThread.join(500);

            return new ShellResult(
                    outputBuffer.toString().trim(),
                    errorBuffer.toString().trim(),
                    process.exitValue()
            );
        } finally {
            if (outputThread != null && outputThread.isAlive()) {
                outputThread.interrupt();
            }
            if (errorThread != null && errorThread.isAlive()) {
                errorThread.interrupt();
            }
            if (process != null) {
                process.destroy();
            }
        }
    }

    private static void readStream(InputStream inputStream, StringBuilder buffer) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (buffer.length() > 0) {
                    buffer.append("\n");
                }
                buffer.append(line);
            }
        } catch (IOException e) {
            Ln.e("Error reading stream", e);
        }
    }

}
